// Generates an irradiance cube from an environment map using convolution

#version 450

layout (location = 0) in vec2 inUV;
layout (location = 0) out vec4 outColor;

layout (binding = 0) uniform samplerCube samplerEnvMap;

layout(push_constant) uniform PushConsts {
	float deltaPhi;
	float deltaTheta;
} consts;

#define PI 3.1415926535897932384626433832795

const vec2 invAtan = vec2(0.1591, 0.3183);
vec2 SampleSphericalMap(vec3 v)
{
    vec2 uv = vec2(atan(v.z, v.x), asin(v.y));
    uv *= invAtan;
    uv += 0.5;
    return uv;
}

void main()
{
	const float TWO_PI = PI * 2.0;
	const float HALF_PI = PI * 0.5;

	float uvTheta = (inUV.x - 0.5) * TWO_PI;
    float uvPhi = (1.0 - inUV.y) * PI;

	vec3 N;
    N.x = sin(uvPhi) * cos(uvTheta);
    N.y = cos(uvPhi);
    N.z = sin(uvPhi) * sin(uvTheta);

	vec3 T;
	T.x = -1.0 * sin(uvPhi) * sin(uvTheta);
	T.y = 0.0;
	T.z = sin(uvPhi) * cos(uvTheta);

	vec3 B = normalize(cross(T, N));

    vec3 color = vec3(0.0);
	
	uint sampleCount = 0u;
	for (float phi = 0.0; phi < TWO_PI; phi += consts.deltaPhi) {
		for (float theta = 0.0; theta < HALF_PI; theta += consts.deltaTheta) {
			vec3 tempVec = cos(phi) * B + sin(phi) * T;
			vec3 sampleVector = cos(theta) * N + sin(theta) * tempVec;
			color += texture(samplerEnvMap, sampleVector).rgb * cos(theta) * sin(theta);
			sampleCount++;
		}
	}

	outColor = vec4(PI * color / float(sampleCount), 1.0);
	// outColor = vec4(color / float(sampleCount), 1.0);
	// color = color / float(sampleCount);
	// color = color / (color + vec3(1.0));
	// outColor = vec4(color, 1.0);
}
